Skip to content

Conversation

@abe238
Copy link

@abe238 abe238 commented Dec 22, 2025

Summary

Add -t/--tty CLI flag to enable pseudo-terminal (PTY) passthrough for interactive terminal applications.

Problem

Interactive terminal applications (like vim, htop, Claude Code, or any TUI app) fail with setRawMode EPERM when run inside the sandbox because PTY operations are blocked by default.

Solution

This PR exposes the existing allowPty functionality (which already exists in macos-sandbox-utils.ts) via a new CLI flag:

srt --tty vim file.txt
srt -t htop

Changes

  • src/cli.ts: Add -t/--tty flag that sets allowPty: true in the sandbox config
  • README.md: Document the new flag and allowPty config option

Technical Details

When --tty is enabled, the macOS Seatbelt profile adds:

  • (allow pseudo-tty) - Master PTY permission
  • (allow file-ioctl (literal "/dev/ptmx") (regex #"^/dev/ttys")) - Ioctl operations on PTY devices
  • Read/write access to /dev/ptmx and /dev/ttys*

Testing

  • Build passes (npm run build)
  • --help shows new flag
  • --tty flag works with --debug to confirm option is set
  • Pre-commit hooks (eslint, prettier) pass

Notes

  • This is macOS-only; Linux handles PTY access differently
  • Security impact is minimal - PTY access doesn't bypass filesystem/network restrictions

Related issue: #76

🤖 Generated with Claude Code

Add -t/--tty CLI flag to enable pseudo-terminal (PTY) passthrough,
which is required for interactive terminal applications like vim,
htop, or any TUI application.

The flag sets allowPty: true in the sandbox config, enabling:
- Master PTY permissions (pseudo-tty)
- Ioctl operations on /dev/ptmx and /dev/ttys*
- Read/write access to PTY devices

This is macOS-only; Linux handles PTY access differently.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@abe238
Copy link
Author

abe238 commented Dec 22, 2025

Detailed Technical Analysis

Root Cause Investigation

When running interactive terminal applications (like Claude Code) inside srt, users encounter:

Error: setRawMode EPERM
    at ReadStream.setRawMode (node:tty:81:24)

This occurs because:

  1. Node.js readline module calls setRawMode() on stdin to enable character-by-character input
  2. setRawMode() requires ioctl operations on the controlling terminal device (/dev/ttys*)
  3. macOS Seatbelt sandbox blocks ioctl operations on PTY devices by default

Code Path Analysis

The sandbox profile generation in macos-sandbox-utils.ts already supports PTY access:

// Lines 585-598
if (allowPty) {
  profile.push('(allow pseudo-tty)')  // Master PTY permission
  profile.push('(allow file-ioctl')
  profile.push('  (literal "/dev/ptmx")')
  profile.push('  (regex #"^/dev/ttys")')  // Slave TTYs
  profile.push(')')
  profile.push('(allow file-read* file-write*')
  profile.push('  (literal "/dev/ptmx")')
  profile.push('  (regex #"^/dev/ttys")')
  profile.push(')')
}

The allowPty option exists in the config schema (sandbox-config.ts:174-177) and is properly propagated through SandboxManager.wrapWithSandbox() at line 536:

const allowPty = customConfig?.allowPty ?? config?.allowPty

However, there was no CLI flag to enable this option for one-off interactive commands.

Why This Matters

  1. Security tools should be usable - If users can't run interactive applications, they'll either:

    • Skip sandboxing entirely (worse security)
    • Use workarounds that may introduce vulnerabilities
  2. Explicit opt-in is correct - The --tty flag maintains the secure-by-default philosophy while enabling legitimate use cases

  3. The code existed, just wasn't exposed - This PR is minimal because the underlying functionality was already implemented and tested

Security Considerations

PTY access does NOT bypass the core sandbox restrictions:

Restriction With --tty
Filesystem writes Still limited to allowWrite paths
Network access Still limited to allowedDomains
Read restrictions Still respects denyRead

PTY access does allow:

  • Terminal escape sequence injection (limited impact - user is at terminal)
  • Keystroke simulation (only affects the sandboxed process's terminal)
  • Raw mode for character-by-character input

Alternative Solutions Considered

Approach Pros Cons
Config file only Persistent All commands get PTY, not discoverable
CLI flag (this PR) Explicit, per-command Extra flag to remember
Auto-detect TTY Zero friction Silent security relaxation, unpredictable in CI

The CLI flag approach was chosen because:

  • Explicit is better than implicit for security tools
  • Per-command control is more flexible than global config
  • Users can combine with config file for persistent setting

Testing Notes

  • The --tty flag shows correctly in --help
  • Debug mode confirms allowPty: true is set when flag is used
  • Pre-commit hooks (eslint, prettier) pass
  • Build succeeds

For full interactive testing, users should test with actual TUI applications like vim or htop on their macOS system.

@abe238
Copy link
Author

abe238 commented Dec 22, 2025

PS: I love you guys <3 My public GH before Claude Code was almost empty of little green squares. Kudos on the best app of the year.
contributions (1)

@webdevcody
Copy link

we are running into an issue using the https://www.npmjs.com/package/@anthropic-ai/claude-agent-sdk where when sandbox mode is enabled (on mac and windows users) the agent just seems to freeze up. We had to turn off sandbox mode because of it. Hopefully this PR fixes that issue and it can get merge upstream to the claude-agent-sdk

@kkyr
Copy link

kkyr commented Jan 15, 2026

Would love to see this get merged!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants